package com.sam.im.heiqun.sound;

import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.PorterDuff;
import android.media.AudioManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.support.v4.view.ViewConfigurationCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewParent;
import android.view.ViewStub;
import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.google.gson.Gson;
import com.sam.im.heiqun.R;
import com.sam.im.heiqun.app.App;
import com.sam.im.heiqun.entities.MsgEntity;
import com.sam.im.heiqun.sound.entity.ConstantApp;
import com.sam.im.heiqun.sound.propeller.Constant;
import com.sam.im.heiqun.sound.propeller.UserStatusData;
import com.sam.im.heiqun.sound.propeller.VideoInfoData;
import com.sam.im.heiqun.sound.propeller.preprocessing.VideoPreProcessing;
import com.sam.im.heiqun.sound.propeller.ui.RtlLinearLayoutManager;
import com.sam.im.heiqun.sound.receiver.AGEventHandler;
import com.sam.im.heiqun.sound.receiver.MyEngineEventHandler;
import com.sam.im.heiqun.sound.receiver.WorkerThread;
import com.sam.im.heiqun.uis.adapters.ChatRecyclerAdapter;
import com.sam.im.heiqun.utils.ConversationUtils;
import com.sam.im.heiqun.utils.EventBusTypeData;
import com.sam.im.heiqun.utils.ToolsUtils;
import com.yuyh.library.uis.activitys.BaseActivity;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Timer;
import java.util.TimerTask;

import io.agora.rtc.IRtcEngineEventHandler;
import io.agora.rtc.RtcEngine;
import io.agora.rtc.video.VideoCanvas;

public class ChatCallActivity extends BaseActivity implements AGEventHandler {


    private GridVideoViewContainer mGridVideoViewContainer;

    private RelativeLayout mSmallVideoViewDock;
    private RelativeLayout backgroud_title;

    // should only be modified under UI thread
    private final HashMap<Integer, SurfaceView> mUidsList = new HashMap<>(); // uid = 0 || uid == EngineConfig.mUid

    private volatile boolean mVideoMuted = false;//false 视频 true 语音

    private volatile boolean mAudioMuted = false;

    private volatile int mAudioRouting = -1; // Default
    public static boolean isActive = false;
    private int type;
    private int fromid;

    @Override
    public int getContentViewId() {
        return R.layout.activity_call_chat;
    }

    @Override
    public void init(Bundle savedInstanceState) {
        EventBus.getDefault().register(this);
        recLen = 0;
        isActive = true;
        final View layout = findViewById(Window.ID_ANDROID_CONTENT);
        ViewTreeObserver vto = layout.getViewTreeObserver();
        vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                    layout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                } else {
                    layout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                }
                initUIandEvent();
            }
        });
        time();

    }

    @Override
    protected void onRestart() {
        super.onRestart();
        isActive = true;
    }

    @Override
    protected void onResume() {
        super.onResume();
        isActive = true;
    }

    Timer timer = new Timer();

    /**
     * 计时
     */
    public void time() {
        timer.schedule(task, 1000, 1000);
    }

    public static int recLen = 0;
    TimerTask task = new TimerTask() {
        @Override
        public void run() {

            runOnUiThread(new Runnable() {      // UI thread
                @Override
                public void run() {

                    ++recLen;
                    if (recLen < 0) {
                        timer.cancel();
                    }

                }
            });
        }
    };

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        return false;
    }

    String channelName;
    private RtcEngine rtcEngine;

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        return false;
    }

    @Subscribe(threadMode = ThreadMode.MAIN) //在ui线程执行
    public void onBaseEvent(final EventBusTypeData type) {
        if (type.getType() == com.sam.im.heiqun.constant.Constant.TOVIDEOTHREECALL) {
            try {
                JSONObject object = new JSONObject(type.getMsg());
                Log.i("fanhui", "sendId:" + object.getInt("fromId")+"  fromid:"+fromid);
                if (object.getInt("fromId") == fromid){
                    finish();
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }

        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN) //在ui线程执行
    public void onBaseEvent(final Integer types) {
        if (types == com.sam.im.heiqun.constant.Constant.TOMessageTypeRefuseVideoRequest) {
            Log.i("fanhui","TOMessageTypeRefuseVideoRequest");

            finish();
            // EventBus.getDefault().post(new EventBusTypeData(com.sam.im.samim.constant.Constant.SWICHVICEOSHOWVIDEONOTIME, (ToolsUtils.getMyUserId()) + "a" + getTime(recLen)));

        } else if (types == com.sam.im.heiqun.constant.Constant.TOMessageTypeChangeVideoToVoiceRequest) {
            //视频切换音频
            backgroud_title.setVisibility(View.VISIBLE);
            backgroud_title.setBackgroundResource(R.drawable.video_voicw);
            video_icon.setImageResource(R.drawable.btn_voice);
            type = 150;
            rtcEngine.disableVideo();
            resetToVideoDisabledUI();
        } else if (types == com.sam.im.heiqun.constant.Constant.SWICHVICEOSHOWVIDEO) {
            video_icon.setImageResource(R.drawable.btn_video);
            backgroud_title.setVisibility(View.GONE);

            //对方同意切换
            rtcEngine.enableVideo();
            type = 149;
        } else if (types == com.sam.im.heiqun.constant.Constant.SWICHVICEOSHOWVIDEONOTIMREFUSEEXXIT) {
            //对方拒绝切换
            video_icon.setImageResource(R.drawable.btn_voice);
            backgroud_title.setVisibility(View.VISIBLE);
            backgroud_title.setBackgroundResource(R.drawable.video_voicw);
            Toast.makeText(this, getResources().getString(R.string.no_chat), Toast.LENGTH_SHORT).show();
        } else if (types == com.sam.im.heiqun.constant.Constant.SWICHVICEOSHOWVIDEONO) {
            //异常退出
            ConversationUtils conversationUtils = new ConversationUtils(this);
            MsgEntity msgEntity = new MsgEntity();
            msgEntity.setMsgString(getString(R.string.chat_time) + getTime(recLen));
            String msg = new Gson().toJson(msgEntity);
            conversationUtils.sendMsgTime(msg, ChatRecyclerAdapter.TO_USER_EMOJI_TEXT, fromid);
            EventBus.getDefault().post(msgEntity);
            finish();
            Log.i("fanhui","SWICHVICEOSHOWVIDEONO");
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void updateUI(EventBusTypeData event) {
        switch (event.getType()) {
            case com.sam.im.heiqun.constant.Constant.VICEOSHOWVIDEO:
                //音频切换视频
                showQuestion();
                break;
        }
    }

    protected void initUIandEvent() {
        ((App) getApplication()).getWorkerThread().eventHandler().addEventHandler(this);

        Intent i = getIntent();
        type = i.getIntExtra("type", 0);
        fromid = i.getIntExtra("fromid", 0);
        channelName = i.getStringExtra(ConstantApp.ACTION_KEY_CHANNEL_NAME);
        SharedPreferences sp = getSharedPreferences("call_video", Context.MODE_PRIVATE);
        sp.edit().putString("call_friend", fromid + "").commit();
        //uid = i.getStringExtra(ConstantApp.ACTION_KEY_ENCRYPTION_KEY);
        //uids = WeiYuanCommon.getUserId(this);

        final String encryptionKey = getIntent().getStringExtra(ConstantApp.ACTION_KEY_ENCRYPTION_KEY);

        final String encryptionMode = getIntent().getStringExtra(ConstantApp.ACTION_KEY_ENCRYPTION_MODE);

        doConfigEngine(encryptionKey, encryptionMode);

        mGridVideoViewContainer = (GridVideoViewContainer) findViewById(R.id.grid_video_view_container);
        mGridVideoViewContainer.setItemEventHandler(new VideoViewEventListener() {
            @Override
            public void onItemDoubleClick(View v, Object item) {

                if (mUidsList.size() < 2) {
                    return;
                }

                UserStatusData user = (UserStatusData) item;
                int uid = (user.mUid == 0) ? Integer.parseInt(ToolsUtils.getMyUserId()) : user.mUid;

                if (mLayoutType == LAYOUT_TYPE_DEFAULT && mUidsList.size() != 1) {
                    switchToSmallVideoView(uid);
                } else {
                    switchToDefaultVideoView();
                }
            }
        });

        video_icon = (ImageView) findViewById(R.id.video_icon);
        backgroud_title = (RelativeLayout) findViewById(R.id.backgroud_title);
        video_icon.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //音视频切换
                if (type == 150 || type == 152) {
                    //语音切换视频
                    type = 149;
                    backgroud_title.setVisibility(View.GONE);
                    acceptCall(com.sam.im.heiqun.constant.Constant.TOMessageTypeChangeVoiceToVideoRequest);
                } else {
                    type = 150;
                    //视频切换音频
                    video_icon.setImageResource(R.drawable.btn_voice);
                    backgroud_title.setBackgroundResource(R.drawable.video_voicw);
                    backgroud_title.setVisibility(View.VISIBLE);
                    acceptCall(com.sam.im.heiqun.constant.Constant.TOMessageTypeChangeVideoToVoiceRequest);
                    rtcEngine.disableVideo();
                    resetToVideoDisabledUI();
                }
            }
        });
        SurfaceView surfaceV = RtcEngine.CreateRendererView(getApplicationContext());
        ((App) getApplication()).getWorkerThread().getRtcEngine().setupLocalVideo(new VideoCanvas(surfaceV, VideoCanvas.RENDER_MODE_HIDDEN, 0));
        surfaceV.setZOrderOnTop(false);
        surfaceV.setZOrderMediaOverlay(false);

        mUidsList.put(0, surfaceV); // get first surface view

        mGridVideoViewContainer.initViewContainer(getApplicationContext(), 0, mUidsList); // first is now full view
        rtcEngine = rtcEngine();
        if (type == 150 || type == 152) {
            //语音
            rtcEngine.disableVideo();
            backgroud_title.setVisibility(View.VISIBLE);
            backgroud_title.setBackgroundResource(R.drawable.video_voicw);
        } else {
        }
        ((App) getApplication()).getWorkerThread().preview(true, surfaceV, 0);

        ((App) getApplication()).getWorkerThread().joinChannel(channelName, Integer.parseInt(ToolsUtils.getMyUserId()));

        TextView textChannelName = (TextView) findViewById(R.id.channel_name);
        // textChannelName.setText(channelName);

        optional();

        LinearLayout bottomContainer = (LinearLayout) findViewById(R.id.bottom_container);
        FrameLayout.MarginLayoutParams fmp = (FrameLayout.MarginLayoutParams) bottomContainer.getLayoutParams();
        fmp.bottomMargin = virtualKeyHeight() + 16;

    }


    /**
     * 请求切换视频
     */
    public void showQuestion() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage(getResources().getString(R.string.switch_chat));
        builder.setTitle(getResources().getString(R.string.tip));
        builder.setPositiveButton(getResources().getString(R.string.ok), new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
                type = 149;
                rtcEngine.enableVideo();
                backgroud_title.setVisibility(View.GONE);
                video_icon.setImageResource(R.drawable.btn_video);
                acceptCall(com.sam.im.heiqun.constant.Constant.TOMessageTypeAgreeChangeVoiceToVideoRequest);
            }
        });
        builder.setNegativeButton(getResources().getString(R.string.cancel), new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
                backgroud_title.setVisibility(View.VISIBLE);
                backgroud_title.setBackgroundResource(R.drawable.video_voicw);

                video_icon.setImageResource(R.drawable.btn_voice);
                acceptCall(com.sam.im.heiqun.constant.Constant.TOMessageTypeRefuseChangeVoiceToVideoRequest);
            }
        });
        builder.create().show();
    }

    ImageView video_icon;


    //根据秒数转化为时分秒   00:00:00
    public static String getTime(int second) {

        if (second < 60) {
            return second + "秒";
        }
        if (second < 3600) {
            int minute = second / 60;
            second = second - minute * 60;

            return minute + "分" + second + "秒";
        }
        int hour = second / 3600;
        int minute = (second - hour * 3600) / 60;
        second = second - hour * 3600 - minute * 60;
        if (hour < 10) {

            return hour + "时" + minute + "分" + second + "秒";
        }
        if (minute < 10) {
            if (second < 10) {
                return hour + "时" + minute + "分" + second + "秒";
            }
            return hour + "时" + minute + "分" + second + "秒";
        }
        if (second < 10) {
            return hour + "时" + minute + "分" + second + "秒";
        }
        return hour + "时" + minute + "分" + second + "秒";
    }


    public void onClickHideIME(View view) {

        //closeIME(findViewById(R.id.msg_content));

        findViewById(R.id.msg_input_container).setVisibility(View.GONE);
        findViewById(R.id.bottom_action_end_call).setVisibility(View.VISIBLE);
        findViewById(R.id.bottom_action_container).setVisibility(View.VISIBLE);
    }


    private ArrayList<Message> mMsgList;

   /* private void initMessageList() {
        mMsgList = new ArrayList<>();
        RecyclerView msgListView = (RecyclerView) findViewById(R.id.msg_list);

        mMsgAdapter = new InChannelMessageListAdapter(this, mMsgList);
        mMsgAdapter.setHasStableIds(true);
        msgListView.setAdapter(mMsgAdapter);
        msgListView.setLayoutManager(new LinearLayoutManager(this, RecyclerView.VERTICAL, false));
        msgListView.addItemDecoration(new MessageListDecoration());
    }*/

    private void notifyMessageChanged(Message msg) {
        mMsgList.add(msg);

        int MAX_MESSAGE_COUNT = 16;

        if (mMsgList.size() > MAX_MESSAGE_COUNT) {
            int toRemove = mMsgList.size() - MAX_MESSAGE_COUNT;
            for (int i = 0; i < toRemove; i++) {
                mMsgList.remove(i);
            }
        }

        // mMsgAdapter.notifyDataSetChanged();
    }

    private int mDataStreamId;

    private void sendChannelMsg(String msgStr) {
        RtcEngine rtcEngine = ((App) getApplication()).getWorkerThread().getRtcEngine();
        if (mDataStreamId <= 0) {
            mDataStreamId = rtcEngine.createDataStream(true, true); // boolean reliable, boolean ordered
        }

        if (mDataStreamId < 0) {
            String errorMsg = "Create data stream error happened " + mDataStreamId;
            return;
        }

        byte[] encodedMsg;
        try {
            encodedMsg = msgStr.getBytes("UTF-8");
        } catch (UnsupportedEncodingException e) {
            encodedMsg = msgStr.getBytes();
        }

        rtcEngine.sendStreamMessage(mDataStreamId, encodedMsg);
    }

    private void optional() {
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);

        setVolumeControlStream(AudioManager.STREAM_VOICE_CALL);
    }

    private void optionalDestroy() {
    }

    private int getVideoProfileIndex() {
        SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);
        int profileIndex = pref.getInt(ConstantApp.PrefManager.PREF_PROPERTY_PROFILE_IDX, ConstantApp.DEFAULT_PROFILE_IDX);
        if (profileIndex > ConstantApp.VIDEO_PROFILES.length - 1) {
            profileIndex = ConstantApp.DEFAULT_PROFILE_IDX;

            // save the new value
            SharedPreferences.Editor editor = pref.edit();
            editor.putInt(ConstantApp.PrefManager.PREF_PROPERTY_PROFILE_IDX, profileIndex);
            editor.apply();
        }
        return profileIndex;
    }

    private void doConfigEngine(String encryptionKey, String encryptionMode) {
        int vProfile = ConstantApp.VIDEO_PROFILES[getVideoProfileIndex()];

        ((App) getApplication()).getWorkerThread().configEngine(vProfile, encryptionKey, encryptionMode);
    }

    public void onBtn0Clicked(View view) {
        showMessageEditContainer();
    }

    private void showMessageEditContainer() {
        findViewById(R.id.bottom_action_container).setVisibility(View.GONE);
        findViewById(R.id.bottom_action_end_call).setVisibility(View.GONE);
        findViewById(R.id.msg_input_container).setVisibility(View.VISIBLE);

        /*EditText edit = (EditText) findViewById(R.id.msg_content);

        edit.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                if (actionId == EditorInfo.IME_ACTION_SEND
                        || (event != null && event.getAction() == KeyEvent.ACTION_DOWN && event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) {
                    String msgStr = v.getText().toString();
                    if (TextUtils.isEmpty(msgStr)) {
                        return false;
                    }
                    sendChannelMsg(msgStr);

                    v.setText("");

                    Message msg = new Message(Message.MSG_TYPE_TEXT,
                            new User(config().mUid, String.valueOf(config().mUid)), msgStr);
                    notifyMessageChanged(msg);

                    return true;
                }
                return false;
            }
        });*/

        //openIME(edit);
    }

    public void onCustomizedFunctionClicked(View view) {
        if (mVideoMuted) {
            onSwitchSpeakerClicked();
        } else {
            onSwitchCameraClicked();
        }
    }


    private void onSwitchCameraClicked() {
        RtcEngine rtcEngine = rtcEngine();
        rtcEngine.switchCamera();
    }

    private void onSwitchSpeakerClicked() {
        RtcEngine rtcEngine = rtcEngine();
        rtcEngine.setEnableSpeakerphone(mAudioRouting != 3);
    }

    private RtcEngine rtcEngine() {
        return ((App) getApplication()).getWorkerThread().getRtcEngine();
    }

    @Override
    protected void onPause() {
        super.onPause();
        isActive = true;
    }

    @Override
    protected void onDestroy() {
        EventBus.getDefault().unregister(this);
        super.onDestroy();
        timer.cancel();
        recLen = 0;
        isActive = false;
        //   unregisterReceiver(mReceivers);
        optionalDestroy();

        doLeaveChannel();
        event().removeEventHandler(this);

        mUidsList.clear();
    }

    private final MyEngineEventHandler event() {
        return ((App) getApplication()).getWorkerThread().eventHandler();
    }


    private void doLeaveChannel() {
        worker().leaveChannel(channelName);
        worker().preview(false, null, 0);
    }

    private final WorkerThread worker() {
        return ((App) getApplication()).getWorkerThread();
    }

    public void onEndCallClicked(View view) {
        canaleVideo();

    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {

        if ((keyCode == KeyEvent.KEYCODE_BACK)) {
            canaleVideo();
            return false;
        } else {
            return super.onKeyDown(keyCode, event);
        }

    }


    //挂断视频
    public void canaleVideo() {
        timer.cancel();
        //EventBus.getDefault().post(new EventBusTypeData(com.sam.im.samim.constant.Constant.SWICHVICEOSHOWVIDEONOTIME, (ToolsUtils.getMyUserId()) + "a" + getTime(recLen)));
        conversationUtils = new ConversationUtils(this);
        MsgEntity msgEntity = new MsgEntity();
        msgEntity.setMsgString(getString(R.string.chat_time) + getTime(recLen));
        String msg = new Gson().toJson(msgEntity);
        conversationUtils.sendMsgTime(msg, ChatRecyclerAdapter.TO_USER_EMOJI_TEXT, fromid);
        acceptCall(com.sam.im.heiqun.constant.Constant.TOMessageTypeCancleVoiceVideo);
        Log.i("fanhui","canaleVideo");
        finish();
    }

    private ConversationUtils conversationUtils;

    public void acceptCall(int type) {
        MsgEntity msgEntity = new MsgEntity();
        msgEntity.setMsgCodes("");
        msgEntity.setMsgString("");
        msgEntity.setMsgType("");
        String msg = new Gson().toJson(msgEntity);
        conversationUtils = new ConversationUtils(this);
//        if (ChatCallActivity.isActive){?
//            String friend_id = getSharedPreferences("Demo", Context.MODE_PRIVATE).getString("friend_ids", null);
//            conversationUtils.sendMsg(msg, type, Integer.parseInt(friend_id));
//        }else{
        conversationUtils.sendMsg(msg, type, fromid);
//        }

    }


    private VideoPreProcessing mVideoPreProcessing;

    public void onBtnNClicked(View view) {
        if (mVideoPreProcessing == null) {
            mVideoPreProcessing = new VideoPreProcessing();
        }

        ImageView iv = (ImageView) view;
        Object showing = view.getTag();
        if (showing != null && (Boolean) showing) {
            mVideoPreProcessing.enablePreProcessing(false);
            iv.setTag(null);
            iv.clearColorFilter();
        } else {
            mVideoPreProcessing.enablePreProcessing(true);
            iv.setTag(true);
            iv.setColorFilter(getResources().getColor(R.color.agora_blue), PorterDuff.Mode.MULTIPLY);
        }
    }

    public void onVoiceChatClicked(View view) {
        if (mUidsList.size() == 0) {
            return;
        }

        SurfaceView surfaceV = getLocalView();
        ViewParent parent;
        if (surfaceV == null || (parent = surfaceV.getParent()) == null) {
            return;
        }

        RtcEngine rtcEngine = rtcEngine();
        mVideoMuted = !mVideoMuted;

        if (mVideoMuted) {
            rtcEngine.disableVideo();
        } else {
            rtcEngine.enableVideo();
        }

        ImageView iv = (ImageView) view;

        iv.setImageResource(mVideoMuted ? R.drawable.btn_disablevideo : R.drawable.btn_enablevideo);

        hideLocalView(mVideoMuted);

        if (mVideoMuted) {
            resetToVideoDisabledUI();
        } else {
            resetToVideoEnabledUI();
        }
    }

    private SurfaceView getLocalView() {
        for (HashMap.Entry<Integer, SurfaceView> entry : mUidsList.entrySet()) {
            if (entry.getKey() == 0 || entry.getKey() == Integer.parseInt(ToolsUtils.getMyUserId())) {
                return entry.getValue();
            }
        }

        return null;
    }

    private void hideLocalView(boolean hide) {
        int uid = Integer.parseInt(ToolsUtils.getMyUserId());
        doHideTargetView(uid, hide);
    }

    private void doHideTargetView(int targetUid, boolean hide) {
        HashMap<Integer, Integer> status = new HashMap<>();
        status.put(targetUid, hide ? UserStatusData.VIDEO_MUTED : UserStatusData.DEFAULT_STATUS);
        if (mLayoutType == LAYOUT_TYPE_DEFAULT) {
            mGridVideoViewContainer.notifyUiChanged(mUidsList, targetUid, status, null);
        } else if (mLayoutType == LAYOUT_TYPE_SMALL) {
            UserStatusData bigBgUser = mGridVideoViewContainer.getItem(0);
            if (bigBgUser.mUid == targetUid) { // big background is target view
                mGridVideoViewContainer.notifyUiChanged(mUidsList, targetUid, status, null);
            } else { // find target view in small video view list
                mSmallVideoViewAdapter.notifyUiChanged(mUidsList, bigBgUser.mUid, status, null);
            }
        }
    }

    private void resetToVideoEnabledUI() {
        ImageView iv = (ImageView) findViewById(R.id.customized_function_id);
        iv.setImageResource(R.drawable.btn_switch_camera);
        iv.clearColorFilter();

        notifyHeadsetPlugged(mAudioRouting);
    }

    private void resetToVideoDisabledUI() {
        ImageView iv = (ImageView) findViewById(R.id.customized_function_id);
        iv.setImageResource(R.drawable.btn_speaker);
        iv.clearColorFilter();

        notifyHeadsetPlugged(mAudioRouting);
    }

    public void onVoiceMuteClicked(View view) {
        if (mUidsList.size() == 0) {
            return;
        }

        RtcEngine rtcEngine = rtcEngine();
        rtcEngine.muteLocalAudioStream(mAudioMuted = !mAudioMuted);

        ImageView iv = (ImageView) view;

        if (mAudioMuted) {
            iv.setColorFilter(getResources().getColor(R.color.agora_blue), PorterDuff.Mode.MULTIPLY);
        } else {
            iv.clearColorFilter();
        }
    }

    @Override
    public void onFirstRemoteVideoDecoded(int uid, int width, int height, int elapsed) {
        doRenderRemoteUi(uid);
    }

    private void doRenderRemoteUi(final int uid) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (isFinishing()) {
                    return;
                }

                if (mUidsList.containsKey(uid)) {
                    return;
                }

                SurfaceView surfaceV = RtcEngine.CreateRendererView(getApplicationContext());
                mUidsList.put(uid, surfaceV);

                boolean useDefaultLayout = mLayoutType == LAYOUT_TYPE_DEFAULT && mUidsList.size() != 2;

                surfaceV.setZOrderOnTop(!useDefaultLayout);
                surfaceV.setZOrderMediaOverlay(!useDefaultLayout);

                rtcEngine().setupRemoteVideo(new VideoCanvas(surfaceV, VideoCanvas.RENDER_MODE_HIDDEN, uid));

                if (useDefaultLayout) {
                    switchToDefaultVideoView();
                } else {
                    int bigBgUid = mSmallVideoViewAdapter == null ? uid : mSmallVideoViewAdapter.getExceptedUid();
                    switchToSmallVideoView(bigBgUid);
                }
            }
        });
    }

    @Override
    public void onJoinChannelSuccess(String channel, final int uid, int elapsed) {

        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (isFinishing()) {
                    return;
                }

                SurfaceView local = mUidsList.remove(0);

                if (local == null) {
                    return;
                }

                mUidsList.put(uid, local);
            }
        });
    }

    @Override
    public void onUserOffline(int uid, int reason) {
        doRemoveRemoteUi(uid);
    }

    @Override
    public void onExtraCallback(final int type, final Object... data) {

        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (isFinishing()) {
                    return;
                }

                doHandleExtraCallback(type, data);
            }
        });
    }

    private void doHandleExtraCallback(int type, Object... data) {
        int peerUid;
        boolean muted;

        switch (type) {
            case AGEventHandler.EVENT_TYPE_ON_USER_AUDIO_MUTED:
                peerUid = (Integer) data[0];
                muted = (boolean) data[1];

                if (mLayoutType == LAYOUT_TYPE_DEFAULT) {
                    HashMap<Integer, Integer> status = new HashMap<>();
                    status.put(peerUid, muted ? UserStatusData.AUDIO_MUTED : UserStatusData.DEFAULT_STATUS);
                    mGridVideoViewContainer.notifyUiChanged(mUidsList, Integer.parseInt(ToolsUtils.getMyUserId()), status, null);
                }

                break;

            case AGEventHandler.EVENT_TYPE_ON_USER_VIDEO_MUTED:
                peerUid = (Integer) data[0];
                muted = (boolean) data[1];

                doHideTargetView(peerUid, muted);

                break;

            case AGEventHandler.EVENT_TYPE_ON_USER_VIDEO_STATS:
                IRtcEngineEventHandler.RemoteVideoStats stats = (IRtcEngineEventHandler.RemoteVideoStats) data[0];

                if (Constant.SHOW_VIDEO_INFO) {
                    if (mLayoutType == LAYOUT_TYPE_DEFAULT) {
                        mGridVideoViewContainer.addVideoInfo(stats.uid, new VideoInfoData(stats.width, stats.height, stats.delay, stats.receivedFrameRate, stats.receivedBitrate));
                        int uid = Integer.parseInt(ToolsUtils.getMyUserId());
                        int profileIndex = getVideoProfileIndex();
                        String resolution = getResources().getStringArray(R.array.string_array_resolutions)[profileIndex];
                        String fps = getResources().getStringArray(R.array.string_array_frame_rate)[profileIndex];
                        String bitrate = getResources().getStringArray(R.array.string_array_bit_rate)[profileIndex];

                        String[] rwh = resolution.split("x");
                        int width = Integer.valueOf(rwh[0]);
                        int height = Integer.valueOf(rwh[1]);

                        mGridVideoViewContainer.addVideoInfo(uid, new VideoInfoData(width > height ? width : height,
                                width > height ? height : width,
                                0, Integer.valueOf(fps), Integer.valueOf(bitrate)));
                    }
                } else {
                    mGridVideoViewContainer.cleanVideoInfo();
                }

                break;

            case AGEventHandler.EVENT_TYPE_ON_SPEAKER_STATS:
                IRtcEngineEventHandler.AudioVolumeInfo[] infos = (IRtcEngineEventHandler.AudioVolumeInfo[]) data[0];

                if (infos.length == 1 && infos[0].uid == 0) { // local guy, ignore it
                    break;
                }

                if (mLayoutType == LAYOUT_TYPE_DEFAULT) {
                    HashMap<Integer, Integer> volume = new HashMap<>();

                    for (IRtcEngineEventHandler.AudioVolumeInfo each : infos) {
                        peerUid = each.uid;
                        int peerVolume = each.volume;

                        if (peerUid == 0) {
                            continue;
                        }
                        volume.put(peerUid, peerVolume);
                    }
                    mGridVideoViewContainer.notifyUiChanged(mUidsList, Integer.parseInt(ToolsUtils.getMyUserId()), null, volume);
                }

                break;

            case AGEventHandler.EVENT_TYPE_ON_APP_ERROR:
                int subType = (int) data[0];

                if (subType == ConstantApp.AppError.NO_NETWORK_CONNECTION) {
                    //showLongToast(getString(R.string.msg_no_network_connection));
                }

                break;

            case AGEventHandler.EVENT_TYPE_ON_DATA_CHANNEL_MSG:

                peerUid = (Integer) data[0];
                final byte[] content = (byte[]) data[1];
                //notifyMessageChanged(new Message(new User(peerUid, String.valueOf(peerUid)), new String(content)));

                break;

            case AGEventHandler.EVENT_TYPE_ON_AGORA_MEDIA_ERROR: {
                int error = (int) data[0];
                String description = (String) data[1];

                //  notifyMessageChanged(new Message(new User(0, null), error + " " + description));

                break;
            }

            case AGEventHandler.EVENT_TYPE_ON_AUDIO_ROUTE_CHANGED:
                notifyHeadsetPlugged((int) data[0]);

                break;

        }
    }

    private void requestRemoteStreamType(final int currentHostCount) {
    }

    private void doRemoveRemoteUi(final int uid) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (isFinishing()) {
                    return;
                }

                Object target = mUidsList.remove(uid);
                Log.i("fanhui","doRemoveRemoteUi");
                if (target == null) {
                    return;
                }


                int bigBgUid = -1;
                if (mSmallVideoViewAdapter != null) {
                    bigBgUid = mSmallVideoViewAdapter.getExceptedUid();
                }


                if (mLayoutType == LAYOUT_TYPE_DEFAULT || uid == bigBgUid) {
                    switchToDefaultVideoView();
                } else {
                    switchToSmallVideoView(bigBgUid);
                }
            }
        });
    }

    private SmallVideoViewAdapter mSmallVideoViewAdapter;

    private void switchToDefaultVideoView() {
        if (mSmallVideoViewDock != null) {
            mSmallVideoViewDock.setVisibility(View.GONE);
        }
        mGridVideoViewContainer.initViewContainer(getApplicationContext(), Integer.parseInt(ToolsUtils.getMyUserId()), mUidsList);

        mLayoutType = LAYOUT_TYPE_DEFAULT;
    }

    private void switchToSmallVideoView(int bigBgUid) {
        HashMap<Integer, SurfaceView> slice = new HashMap<>(1);
        slice.put(bigBgUid, mUidsList.get(bigBgUid));
        mGridVideoViewContainer.initViewContainer(getApplicationContext(), bigBgUid, slice);

        bindToSmallVideoView(bigBgUid);

        mLayoutType = LAYOUT_TYPE_SMALL;

        requestRemoteStreamType(mUidsList.size());
    }

    public int mLayoutType = LAYOUT_TYPE_DEFAULT;

    public static final int LAYOUT_TYPE_DEFAULT = 0;

    public static final int LAYOUT_TYPE_SMALL = 1;

    private void bindToSmallVideoView(int exceptUid) {
        if (mSmallVideoViewDock == null) {
            ViewStub stub = (ViewStub) findViewById(R.id.small_video_view_dock);
            mSmallVideoViewDock = (RelativeLayout) stub.inflate();
        }

        boolean twoWayVideoCall = mUidsList.size() == 2;

        RecyclerView recycler = (RecyclerView) findViewById(R.id.small_video_view_container);

        boolean create = false;

        if (mSmallVideoViewAdapter == null) {
            create = true;
            mSmallVideoViewAdapter = new SmallVideoViewAdapter(this, Integer.parseInt(ToolsUtils.getMyUserId())
                    , exceptUid, mUidsList, new VideoViewEventListener() {
                @Override
                public void onItemDoubleClick(View v, Object item) {
                    switchToDefaultVideoView();
                }
            });
            mSmallVideoViewAdapter.setHasStableIds(true);
        }
        recycler.setHasFixedSize(true);


        if (twoWayVideoCall) {
            recycler.setLayoutManager(new RtlLinearLayoutManager(this, RtlLinearLayoutManager.HORIZONTAL, false));
        } else {
            recycler.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));
        }
        recycler.addItemDecoration(new SmallVideoViewDecoration());
        recycler.setAdapter(mSmallVideoViewAdapter);

        recycler.setDrawingCacheEnabled(true);
        recycler.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_AUTO);

        if (!create) {
            mSmallVideoViewAdapter.setLocalUid(Integer.parseInt(ToolsUtils.getMyUserId()));
            mSmallVideoViewAdapter.notifyUiChanged(mUidsList, exceptUid, null, null);
        }
        recycler.setVisibility(View.VISIBLE);
        mSmallVideoViewDock.setVisibility(View.VISIBLE);
    }

    public void notifyHeadsetPlugged(final int routing) {

        mAudioRouting = routing;

        if (!mVideoMuted) {
            return;
        }

        ImageView iv = (ImageView) findViewById(R.id.customized_function_id);
        if (mAudioRouting == 3) { // Speakerphone
            iv.setColorFilter(getResources().getColor(R.color.agora_blue), PorterDuff.Mode.MULTIPLY);
        } else {
            iv.clearColorFilter();
        }
    }

    protected int virtualKeyHeight() {
        boolean hasPermanentMenuKey = ViewConfigurationCompat.hasPermanentMenuKey(ViewConfiguration.get(getApplication()));

        DisplayMetrics metrics = new DisplayMetrics();
        Display display = getWindowManager().getDefaultDisplay();

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            display.getRealMetrics(metrics);
        } else {
            display.getMetrics(metrics);
        }

        int fullHeight = metrics.heightPixels;

        display.getMetrics(metrics);

        return fullHeight - metrics.heightPixels;
    }
}
